package com.qf.mybatisplus.utils;


import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author MR.Zhang
 * @Title: ImgUtil
 * @ProjectName hzmoko
 * @Description: TODO
 * @date 2019-1-915:54
 */
public class ImgUtil {

    /**
     * @function：根据图片完整路径，判断是横版还是竖版图片
     * @param imagePath
     * @return true是竖版，false是横版
     */
    public static boolean getVerticalImage(String imagePath) {
        boolean is_vertical = false;
        BufferedImage bufferedImage;
        try {
            bufferedImage = ImageIO.read(new File(imagePath));
            int height = bufferedImage.getHeight();
            int width = bufferedImage.getWidth();
            if (height > width) {
                // 竖版
                is_vertical = true;
            } else {
                // 横版
                is_vertical = false;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return is_vertical;
    }

    /**
     *
     * @param bufferedImage
     *            图片
     * @param angel
     *            旋转角度
     * @return
     */
    public static BufferedImage rotateImage(BufferedImage bufferedImage, int angel) {
        if (bufferedImage == null) {
            return null;
        }
        if (angel < 0) {
            // 将负数角度，纠正为正数角度
            angel = angel + 360;
        }
        int imageWidth = bufferedImage.getWidth(null);
        int imageHeight = bufferedImage.getHeight(null);
        // 计算重新绘制图片的尺寸
        Rectangle rectangle = calculatorRotatedSize(new Rectangle(new Dimension(imageWidth, imageHeight)), angel);
        // 获取原始图片的透明度
        int type = bufferedImage.getColorModel().getTransparency();
        BufferedImage newImage = null;
        newImage = new BufferedImage(rectangle.width, rectangle.height, type);
        Graphics2D graphics = newImage.createGraphics();
        // 平移位置
        graphics.translate((rectangle.width - imageWidth) / 2, (rectangle.height - imageHeight) / 2);
        // 旋转角度
        graphics.rotate(Math.toRadians(angel), imageWidth / 2, imageHeight / 2);
        // 绘图
        graphics.drawImage(bufferedImage, null, null);
        return newImage;
    }

    /**
     * 旋转图片
     *
     * @param image
     *            图片
     * @param angel
     *            旋转角度
     * @return
     */
    public static BufferedImage rotateImage(Image image, int angel) {
        if (image == null) {
            return null;
        }
        if (angel < 0) {
            // 将负数角度，纠正为正数角度
            angel = angel + 360;
        }
        int imageWidth = image.getWidth(null);
        int imageHeight = image.getHeight(null);
        Rectangle rectangle = calculatorRotatedSize(new Rectangle(new Dimension(imageWidth, imageHeight)), angel);
        BufferedImage newImage = null;
        newImage = new BufferedImage(rectangle.width, rectangle.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = newImage.createGraphics();
        // transform
        graphics.translate((rectangle.width - imageWidth) / 2, (rectangle.height - imageHeight) / 2);
        graphics.rotate(Math.toRadians(angel), imageWidth / 2, imageHeight / 2);
        graphics.drawImage(image, null, null);
        return newImage;
    }

    /**
     * 计算旋转后的尺寸
     *
     * @param src
     * @param angel
     * @return
     */
    private static Rectangle calculatorRotatedSize(Rectangle src, int angel) {
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }
        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

    /**
     * 旋转
     *
     * @param degree
     *            旋转角度
     * @throws Exception
     */
    public static void spin(String src,int degree,String dest,String suffix) throws Exception {
        int swidth = 0; // 旋转后的宽度
        int sheight = 0; // 旋转后的高度
        int x; // 原点横坐标
        int y; // 原点纵坐标

        File file = new File(src);
        if (!file.isFile()) {
            throw new Exception("ImageDeal>>>" + file + " 不是一个图片文件!");
        }
        Image img=Toolkit.getDefaultToolkit().getImage(file.getPath());
        BufferedImage bi =toBufferedImage(img);
        //BufferedImage bi = ImageIO.read(file); // 读取该图片
        // 处理角度--确定旋转弧度
        degree = degree % 360;
        if (degree < 0)
            degree = 360 + degree;// 将角度转换到0-360度之间
        double theta = Math.toRadians(degree);// 将角度转为弧度

        // 确定旋转后的宽和高
        if (degree == 180 || degree == 0 || degree == 360) {
            swidth = bi.getWidth();
            sheight = bi.getHeight();
        } else if (degree == 90 || degree == 270) {
            sheight = bi.getWidth();
            swidth = bi.getHeight();
        } else {
            swidth = (int) (Math.sqrt(bi.getWidth() * bi.getWidth()
                    + bi.getHeight() * bi.getHeight()));
            sheight = (int) (Math.sqrt(bi.getWidth() * bi.getWidth()
                    + bi.getHeight() * bi.getHeight()));
        }

        x = (swidth / 2) - (bi.getWidth() / 2);// 确定原点坐标
        y = (sheight / 2) - (bi.getHeight() / 2);

        BufferedImage spinImage = new BufferedImage(swidth, sheight,
                bi.getType());
        // 设置图片背景颜色
        Graphics2D gs = (Graphics2D) spinImage.getGraphics();
        gs.setColor(Color.white);
        gs.fillRect(0, 0, swidth, sheight);// 以给定颜色绘制旋转后图片的背景

        AffineTransform at = new AffineTransform();
        at.rotate(theta, swidth / 2, sheight / 2);// 旋转图象
        at.translate(x, y);
        AffineTransformOp op = new AffineTransformOp(at,
                AffineTransformOp.TYPE_BICUBIC);
        spinImage = op.filter(bi, spinImage);
        File sf = new File(dest);
        ImageIO.write(spinImage, suffix, sf); // 保存图片

    }


    public static BufferedImage toBufferedImage(Image image) {
        if (image instanceof BufferedImage) {
            return (BufferedImage) image;
        }
        // This code ensures that all the pixels in the image are loaded
        image = new ImageIcon(image).getImage();
        BufferedImage bimage = null;
        GraphicsEnvironment ge = GraphicsEnvironment
                .getLocalGraphicsEnvironment();
        try {
            int transparency = Transparency.OPAQUE;
            GraphicsDevice gs = ge.getDefaultScreenDevice();
            GraphicsConfiguration gc = gs.getDefaultConfiguration();
            bimage = gc.createCompatibleImage(image.getWidth(null),
                    image.getHeight(null), transparency);
        } catch (HeadlessException e) {
            // The system does not have a screen
        }
        if (bimage == null) {
            // Create a buffered image using the default color model
            int type = BufferedImage.TYPE_INT_RGB;
            bimage = new BufferedImage(image.getWidth(null),
                    image.getHeight(null), type);
        }
        // Copy image to buffered image
        Graphics g = bimage.createGraphics();
        // Paint the image onto the buffered image
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return bimage;
    }

    /**
     * 一张以某种颜色为背景的图片，提取其中有效内容，并裁剪多余的部分，最后缩放到指定宽度的图片
     * 应用：在一张白纸上签字的图片，获取签字内容，并缩放到指定大小
     * @param file
     * @param w 宽度
     * @param RGB -1为白色
     * @Author cola.Niu
     * @return
     */
    public static Image extractAndClipImageOfColorBack(File file,int w,int RGB) throws IOException {
        BufferedImage bi = ImageIO.read(file);
        int heigth = bi.getHeight();
        int width = bi.getWidth();
        int top = 0,left = 0,right = width-1,bottom = heigth-1;
        top :for (int i = 1; i < heigth-1; i+=2) {
            for (int j = 0; j < width; j++) {
                int rgb = bi.getRGB(j,i);
                if (rgb!=RGB){
                    top = i-1;
                    break top;
                }
            }
        }
        bottom:for (int i = heigth-2; i >0; i-=2) {
            for (int j = 0; j < width; j++) {
                int rgb = bi.getRGB(j,i);
                if (rgb!=RGB){
                    bottom = i+1;
                    break bottom;
                }
            }
        }
        left:for (int i = 1; i <width-1; i+=2) {
            for (int j = 0; j < heigth; j++) {
                int rgb = bi.getRGB(i,j);
                if (rgb!=RGB){
                    left = i-1;
                    break left;
                }
            }
        }
        right:for (int i = width-2; i >0; i-=2) {
            for (int j = 0; j < heigth; j++) {
                int rgb = bi.getRGB(i,j);
                if (rgb!=RGB){
                    right = i+1;
                    break right;
                }
            }
        }
        //修正，外层加5像素空白
        top = (top-5)>0?(top-5):0;
        bottom = (bottom+5)>heigth?heigth:(bottom+5);
        left = (left-5)>0?(left-5):0;
        right = (right+5)>width?width:(right+5);
        //裁剪
        bi = bi.getSubimage(left,top,right-left,bottom-top);
        Image image = bi.getScaledInstance(w,w*(bottom-top)/(right-left), Image.SCALE_FAST);
        bi.flush();
        return image;
    }

    /**
     * 将多张图片按照某种规则整合为一张图片
     * 规则为：提取图片中有用部分（如一张白纸中的签名），裁剪，缩放到指定宽度，合成
     * 目前是纵向合成，后期增加合成方向
     * @param files
     * @param targetPath
     * @param w
     * @param RGB
     * @throws IOException
     * @Author cola.Niu
     */
    public static void mergeAndModifyImages(List<File> files,String targetPath,int w,int amountOfColumn,int gap,int RGB)throws IOException{
        //对入参进行判断
        List<Image>  images = new ArrayList<>();
        List<Integer> heights = new ArrayList<>();
        //计算多少行
        int amountOfLine = (files.size()+amountOfColumn-1)/amountOfColumn;
        //每行的最大高度
        int[] heightOfEveryLine = new int[amountOfLine];

        for (int i = 0,line = 0; i < files.size(); i++) {

            File file = files.get(i);
            Image image = extractAndClipImageOfColorBack(file,w,RGB);
            int h = image.getHeight(null);
            heights.add(h);
            images.add(image);
            if(heightOfEveryLine[line]<h)
                heightOfEveryLine[line] = h;
            if ((i+1)%amountOfColumn==0)
                line++;//换行
        }

        //获取总高
        int totalHeight = 0;
        for (int i : heightOfEveryLine) {
            totalHeight+=i;
        }

        BufferedImage bi2 = new BufferedImage(w*amountOfColumn+gap*(amountOfColumn-1),totalHeight+gap*amountOfLine,1);
        //x横坐标，y纵坐标
        int x = 0,y = 0;

        //设置背景色
        Graphics graphics = bi2.getGraphics();
        graphics.setColor(new Color(RGB));
        graphics.fillRect(0, 0, bi2.getWidth(), bi2.getHeight());
        //拼图
        for (int i = 0,line = 0; i < images.size(); i++) {
            Image image = images.get(i);
            graphics.drawImage(image,x,y,null);
            if ((i+1)%amountOfColumn==0){
                //换行
                x=0;
                y+=heightOfEveryLine[line]+gap;
                line++;
            }else {
                //当前行
                x+=(w+gap);
            }
        }
        File img = new File(targetPath);
        if (!img.getParentFile().exists()) {
            img.getParentFile().mkdirs();
        }
        ImageIO.write(bi2,"png",new File(targetPath));
    }

    /**
     *叠加合成
     * @param srcBufferImg
     * @param waterImg
     * @param x
     * @param y
     * @param alpha
     */
    public static BufferedImage megPic(BufferedImage srcBufferImg,BufferedImage waterImg,int x,int y,float alpha){

        // 创建Graphics2D对象，用在底图对象上绘图
        Graphics2D g2d = srcBufferImg.createGraphics();
        int waterImgWidth = waterImg.getWidth();// 获取层图的宽度
        int waterImgHeight = waterImg.getHeight();// 获取层图的高度
        // 在图形和图像中实现混合和透明效果
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha));
        // 绘制
        g2d.drawImage(waterImg, x, y, waterImgWidth, waterImgHeight, null);
        g2d.dispose();// 释放图形上下文使用的系统资源

        return srcBufferImg;
    }

    /**
     * 图片透明化
     * @param imgSrc
     * @return
     */
    public static  BufferedImage transferAlpha(BufferedImage imgSrc) {

        // 如果是MultipartFile类型，那么自身也有转换成流的方法：is = file.getInputStream();
        Image image = (Image) imgSrc;
        ImageIcon imageIcon = new ImageIcon(image);
        BufferedImage bufferedImage = new BufferedImage(imageIcon.getIconWidth(), imageIcon.getIconHeight(),
                BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics();
        g2D.drawImage(imageIcon.getImage(), 0, 0, imageIcon.getImageObserver());
        int alpha = 0;
        for (int j1 = bufferedImage.getMinY(); j1 < bufferedImage.getHeight(); j1++) {
            for (int j2 = bufferedImage.getMinX(); j2 < bufferedImage.getWidth(); j2++) {
                int rgb = bufferedImage.getRGB(j2, j1);
                int R = (rgb & 0xff0000) >> 16;
                int G = (rgb & 0xff00) >> 8;
                int B = (rgb & 0xff);
                if (((255 - R) < 30) && ((255 - G) < 30) && ((255 - B) < 30)) {
                    rgb = ((alpha + 1) << 24) | (rgb & 0x00ffffff);
                }
                bufferedImage.setRGB(j2, j1, rgb);
            }
        }
        g2D.drawImage(bufferedImage, 0, 0, imageIcon.getImageObserver());
        return bufferedImage;
    }

    /**
     * 实现图片缩放，都是通过bufferedImage来操作
     * @param read
     * @param width
     * @param height
     * @return
     */
    public static BufferedImage zoomImg(BufferedImage read,int width,int height){

        //调用缩放方法获取缩放后的图片
        Image img = read.getScaledInstance(width , height, Image.SCALE_SMOOTH);
        //创建一个新的缓存图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔
        Graphics2D graphics = image.createGraphics();
        //将Image对象画在画布上,最后一个参数,ImageObserver:接收有关 Image 信息通知的异步更新接口,没用到直接传空
        graphics.drawImage(img, 0, 0,null);
        //一定要释放资源
        graphics.dispose();
        //获取到文件的后缀名
        return image;
    }

    public static BufferedImage createAWhitePicture(int width,int height){
        //创建一个新的缓存图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        //获取画笔
        Graphics graphics = image.getGraphics();
        graphics.setColor(new Color(-1));
        graphics.fillRect(0,0,width,height);
        return image;
    }

    /**
     * 向图片中写入文字
     * @param image
     * @param text
     * @param x
     * @param y
     * @return
     */
    public static BufferedImage fillText(BufferedImage image,String text,int x,int y){
        //获取画笔
        Graphics graphics = image.getGraphics();
        graphics.setColor(Color.BLACK);
        graphics.setFont(new Font("宋体",0,40));
        graphics.drawString(text,x,y);
        return image;
    }

    /**
     * 将指定图片读成bufferImg
     * @param srcImagePath
     * @return
     */
    public static BufferedImage readToBufferImg(String srcImagePath) throws IOException {
        //使用ImageIO的read方法读取图片
        File srcImageFile = new File(srcImagePath);
        BufferedImage read = ImageIO.read(srcImageFile);
        return read;
    }

    /**
     * 将bufferImg输出成png图片
     * @param bufferedImage
     * @param targetPath
     * @throws IOException
     */
    public static void bufferImgToFile(BufferedImage bufferedImage,String targetPath) throws IOException {
        ImageIO.write(bufferedImage,"png",new File(targetPath));
    }


    public static File imgToPdf(String path, String mOutputPdfFileName) {
        Document doc = new Document(PageSize.A4, 20, 20, 20, 20); //new一个pdf文档
        try {
            PdfWriter.getInstance(doc, new FileOutputStream(mOutputPdfFileName)); //pdf写入
            doc.open();//打开文档
            doc.newPage();  //在pdf创建一页
            com.itextpdf.text.Image png1 = com.itextpdf.text.Image.getInstance(path); //通过文件路径获取image
            float heigth = png1.getHeight();
            float width = png1.getWidth();
            int percent = getPercent2(heigth, width);
            png1.setAlignment(com.itextpdf.text.Image.MIDDLE);
            png1.scalePercent(percent + 3);// 表示是原来图像的比例;
            doc.add(png1);
            doc.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        File mOutputPdfFile = new File(mOutputPdfFileName);  //输出流
        if (!mOutputPdfFile.exists()) {
            mOutputPdfFile.deleteOnExit();
            return null;
        }
        return mOutputPdfFile; //反回文件输出流
    }

    private static int getPercent(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        if (h > w) {
            p2 = 297 / h * 100;
        } else {
            p2 = 210 / w * 100;
        }
        p = Math.round(p2);
        return p;
    }

    private static int getPercent2(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        p2 = 530 / w * 100;
        p = Math.round(p2);
        return p;
    }

}
